#pragma once

#include <iostream>
#include <unordered_map>
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <functional>
// add by zl 20250520 模版类
// 把指针转化成句柄，方便释放安全释放
//static std::shared_ptr<T> GetPtr(int32_t oHandle) 注意上层使用时候, 返回值用局部变量存储，保证每次获取句柄都通过内部管理
// 通过此模版类，可以解决线程安全问题
template<typename T>
class ConvertHandle {

public:
	// rawPtr 是裸指针，deleter 是默认析构函数，如果裸指针不是new 出来的，请自定义析构函数

	static int32_t CreateHandle(T* rawPtr, std::function<void(T*)> deleter = [](T* p) { delete p; })
	{
		return ConvertHandle::getInstance().CreateHandleInternal(rawPtr, deleter);
	}
	static int32_t DestroyHandle(int32_t oHandle)
	{
		return ConvertHandle::getInstance().DestroyHandleInternal(oHandle);
	}

	static std::shared_ptr<T> GetPtr(int32_t oHandle)
	{
		return ConvertHandle::getInstance().GetPtrInternal(oHandle);
	}

private:

	int32_t CreateHandleInternal(T* rawPtr, std::function<void(T*)> deleter = [](T* p) { delete p; })
	{
		if (!rawPtr)
		{
			return -1;
		}

		std::shared_ptr<T> sharePtr = std::shared_ptr<T>(rawPtr, deleter);

	
		std::lock_guard<std::mutex> lock(m_mutexHandle);
		do {
			m_index = (m_index >= INT32_MAX - 1) ? 1 : m_index + 1;
		} while (m_mapHandle.find(m_index) != m_mapHandle.end());

		m_mapHandle[m_index] = std::move(sharePtr);
		
		return m_index;
	}
	int32_t DestroyHandleInternal(int32_t oHandle)
	{
		std::shared_ptr<T> ptr = GetPtrInternal(oHandle, true);
		if (ptr)
		{

			std::mutex t_mutex;
			std::condition_variable t_condition;

			while (1)
			{
				if (ptr.use_count() == 1)
				{
					ptr.reset();
					break;
				}
				//std::this_thread::sleep_for(std::chrono::milliseconds(1));

				std::unique_lock<std::mutex> lock(t_mutex);
				t_condition.wait_for(lock, std::chrono::milliseconds(1));
			}
		}
		return 0;

	}
	std::shared_ptr<T> GetPtrInternal(int32_t oHandle, bool isErase = false)
	{
		std::shared_ptr<T> ptr;
		std::lock_guard<std::mutex> lk(m_mutexHandle);
		typename std::unordered_map<int32_t, std::shared_ptr<T>>::iterator it = m_mapHandle.find(oHandle);
		if (it != m_mapHandle.end())
		{
			ptr = it->second;
			if (isErase)
			{
				m_mapHandle.erase(it);
			}
		}
		return ptr;
	}


	static ConvertHandle<T>& getInstance() {
		std::call_once(m_initFlag, []() {
			m_oInstance = new ConvertHandle<T>();
			});
		return *m_oInstance;
	}

private:
	std::unordered_map<int32_t, std::shared_ptr<T>> m_mapHandle;
	std::mutex m_mutexHandle;
	int32_t m_index = 0;


	static ConvertHandle* m_oInstance;
	static std::once_flag m_initFlag;
};


template<typename T>
std::once_flag ConvertHandle<T>::m_initFlag;

template<typename T>
ConvertHandle<T>* ConvertHandle<T>::m_oInstance = nullptr;
